﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using DalGen.Interf;
using System.Xml;
using System.Data.SqlClient;
using System.Data;
using DalGen.Entity;
using NVelocity;
using System.IO;
using DalGen.Util;

namespace DalGen.Impl
{
	public class SqlBuilder : BuilderBase, IBuilder
	{
		protected SqlConnection _conn;

		public SqlBuilder()
		{
			string sSplit = System.AppDomain.CurrentDomain.BaseDirectory.Substring(System.AppDomain.CurrentDomain.BaseDirectory.Length - 1);
			string ConfigPath;
			if (sSplit != @"\" && sSplit != "/")
				ConfigPath = System.AppDomain.CurrentDomain.BaseDirectory + @"\";
			else
				ConfigPath = System.AppDomain.CurrentDomain.BaseDirectory;
			string sConfigFileName = ConfigPath + @"Reflection\SQL2DotNet.xml";
			domSql2DotNet = new XmlDocument();
			domSql2DotNet.Load(sConfigFileName);

		}


		public void ConnectToDB()
		{
			string sConnString = ConnectionString;
			_conn = new SqlConnection(sConnString);
			_conn.Open();
		}

		public void DisconnectFromDB()
		{
			if (_conn.State == ConnectionState.Open)
			{
				_conn.Close();
			}
		}

		public string ConnectionString { get; set; }


		public System.Data.DataTable GetAllTables()
		{
			ConnectToDB();
			//SqlCommand sqlComm = new SqlCommand("sp_tables", _conn);
			//sqlComm.CommandType = CommandType.StoredProcedure;
			//'

			SqlCommand sqlComm = new SqlCommand("select name from sysobjects where type = 'U'", _conn);
			sqlComm.CommandType = CommandType.Text;
			SqlDataAdapter sdaTables = new SqlDataAdapter(sqlComm);
			DataTable dtTables = new DataTable();
			sdaTables.Fill(dtTables);
			DisconnectFromDB();
			return dtTables;
		}

		// 获取指定表的主键
		public DataTable GetPrimaryKeys(string sTableName)
		{
			ConnectToDB();
			DataTable dtPkey = new DataTable("PrimaryKeys");
			SqlCommand sqlComm = new SqlCommand("sp_pkeys", _conn);
			sqlComm.CommandType = CommandType.StoredProcedure;

			SqlParameter sqlParam = new SqlParameter();
			sqlParam.ParameterName = "@table_name";
			sqlParam.SqlDbType = SqlDbType.VarChar;
			sqlParam.Size = 200;
			sqlParam.Direction = ParameterDirection.Input;
			sqlParam.Value = sTableName;
			sqlComm.Parameters.Add(sqlParam);

			SqlDataAdapter sqlDpt = new SqlDataAdapter(sqlComm);
			sqlDpt.Fill(dtPkey);
			DisconnectFromDB();
			return dtPkey;
		}


		public List<TableInfo> GetColumns(string dataBaseName, string sTableName)
		{

			string strSql = @"select 
[ColumnName]=[Columns].name,
[SystemTypeName]=[Types].name,
[Precision]=[Columns].precision,
[Scale]=[Columns].scale,
[MaxLength]=[Columns].max_length,
[IsNullable]=[Columns].is_nullable,
[IsRowGUIDCol]=[Columns].is_rowguidcol,
[IsIdentity]=[Columns].is_identity,
[IsComputed]=[Columns].is_computed,
[IsXmlDocument]=[Columns].is_xml_document,
[Description]=[Properties].value
from sys.tables as [Tables]
inner join sys.columns as [Columns]
on [Tables].object_id=[Columns].object_id
inner join sys.types as [Types]
on [Columns].system_type_id=[Types].system_type_id and is_user_defined=0 and [Types].name<>'sysname'
left outer join sys.extended_properties as [Properties]
on [Properties].major_id=[Tables].object_id and [Properties].minor_id=[Columns].column_id and [Properties].name='MS_Description'
where [Tables].name='" + sTableName + "' order by [Columns].column_id";

			// 获取字段
			DataTable dtColumn = new DataTable("Columns");
			SqlDataAdapter da = new SqlDataAdapter();
			da.SelectCommand = new SqlCommand(strSql, _conn);
			da.Fill(dtColumn);

			// 获取表的主键
			DataTable dtPkey = GetPrimaryKeys(sTableName);

			List<TableInfo> list = new List<TableInfo>();

			foreach (DataRow row in dtColumn.Rows)
			{
				TableInfo entity = new TableInfo();
				string sDataType = row["SystemTypeName"].ToString();

				entity.ColumnName = row["ColumnName"].ToString();

				// 判断列是否为主键
				if (dtPkey.Select("COLUMN_NAME='" + (string)row["ColumnName"] + "'").Length != 0)
					entity.IsPK = true;
				else
					entity.IsPK = false;

                if ((bool)row["IsIdentity"])
                    entity.Identity = true;
                else
                    entity.Identity = false;


				if (string.IsNullOrEmpty(row["Description"].ToString()))
				{
					entity.Remark = row["ColumnName"].ToString();
				}
				else
				{
					entity.Remark = row["Description"].ToString().Replace("\r\n","");
				}

				entity.Type = GetLanguageTypeName(sDataType);

				entity.DbType = GetDbTypeName(sDataType);

				list.Add(entity);

			}

			return list;
		}


		public string BuilderEntity(BuilderInfo info)
		{


			//从文件中读取模板
			Template template = velocity.GetTemplate("Template/IBatis/DataEntity.vm");
			context.Put("list", info);

			//合并模板
			StringWriter writer = new StringWriter();
			template.Merge(context, writer);

			DirectoryInfo dic = new DirectoryInfo(info.EntitySavePath);
			dic.Create();

			using (StreamWriter writerFile = new StreamWriter(info.EntitySavePath + "/E" + info.TableName + ".cs", false, Encoding.UTF8, 200))
			{
				writerFile.Write(writer);
				writerFile.Flush();
				writerFile.Close();
			}

			return writer.ToString();
		}


		public string BuilderMap(BuilderInfo info)
		{
			//从文件中读取模板
			Template template = velocity.GetTemplate("Template/IBatis/Mapping.vm");
			context.Put("list", info);
			//合并模板
			StringWriter writer = new StringWriter();
			template.Merge(context, writer);

			DirectoryInfo dic = new DirectoryInfo(info.MapXmlSavePath);
			dic.Create();

			using (StreamWriter writerFile = new StreamWriter(info.MapXmlSavePath + "/" + info.TableName + ".xml", false, Encoding.UTF8, 200))
			{
				writerFile.Write(writer);
				writerFile.Flush();
				writerFile.Close();
			}



			return writer.ToString();
		}


		public string BuilderIRepository(BuilderInfo info)
		{

			//从文件中读取模板
			Template template = velocity.GetTemplate("Template/IBatis/IRepository.vm");
			context.Put("list", info);
			context.Put("StringHelper", new StringHelper());
			//合并模板
			StringWriter writer = new StringWriter();
			template.Merge(context, writer);

			DirectoryInfo dic = new DirectoryInfo(info.IRepositorySavePath);
			dic.Create();

			using (StreamWriter writerFile = new StreamWriter(info.IRepositorySavePath + "/I" + info.TableName + ".cs", false, Encoding.UTF8, 200))
			{
				writerFile.Write(writer);
				writerFile.Flush();
				writerFile.Close();
			}


			return writer.ToString();
		}


		public string BuilderIService(BuilderInfo info)
		{

			//从文件中读取模板
			Template template = velocity.GetTemplate("Template/IBatis/IService.vm");
			context.Put("list", info);
			context.Put("StringHelper", new StringHelper());
			//合并模板
			StringWriter writer = new StringWriter();
			template.Merge(context, writer);

			DirectoryInfo dic = new DirectoryInfo(info.IServiceSavePath);
			dic.Create();

			using (StreamWriter writerFile = new StreamWriter(info.IServiceSavePath + "/I" + info.TableName + "Service.cs", false, Encoding.UTF8, 200))
			{
				writerFile.Write(writer);
				writerFile.Flush();
				writerFile.Close();
			}


			return writer.ToString();
		}


		public string BuilderService(BuilderInfo info)
		{

			//从文件中读取模板
			Template template = velocity.GetTemplate("Template/IBatis/Service.vm");
			context.Put("list", info);
			context.Put("StringHelper", new StringHelper());
			//合并模板
			StringWriter writer = new StringWriter();
			template.Merge(context, writer);

			DirectoryInfo dic = new DirectoryInfo(info.ServiceSavePath);
			dic.Create();

			using (StreamWriter writerFile = new StreamWriter(info.ServiceSavePath + "/" + info.TableName + "Service.cs", false, Encoding.UTF8, 200))
			{
				writerFile.Write(writer);
				writerFile.Flush();
				writerFile.Close();
			}


			return writer.ToString();
		}

		public string BuilderRepository(BuilderInfo info)
		{
			//从文件中读取模板
			Template template = velocity.GetTemplate("Template/IBatis/Repository.vm");
			context.Put("list", info);
			context.Put("StringHelper", new StringHelper());
			//合并模板
			StringWriter writer = new StringWriter();
			template.Merge(context, writer);

			DirectoryInfo dic = new DirectoryInfo(info.RepositorySavePath);
			dic.Create();

			using (StreamWriter writerFile = new StreamWriter(info.RepositorySavePath + "/" + info.TableName + "Repository.cs", false, Encoding.UTF8, 200))
			{
				writerFile.Write(writer);
				writerFile.Flush();
				writerFile.Close();
			}


			return writer.ToString();
		}

        public string BuilderServiceModel(BuilderInfo info)
        {


            //从文件中读取模板
            Template template = velocity.GetTemplate("Template/IBatis/ServiceModel.vm");
            context.Put("list", info);

            //合并模板
            StringWriter writer = new StringWriter();
            template.Merge(context, writer);

            DirectoryInfo dic = new DirectoryInfo(info.ServiceModelSavePath);
            dic.Create();

            using (StreamWriter writerFile = new StreamWriter(info.ServiceModelSavePath + "/" + info.TableName + "Model.cs", false, Encoding.UTF8, 200))
            {
                writerFile.Write(writer);
                writerFile.Flush();
                writerFile.Close();
            }

            return writer.ToString();
        }

        public string BuilderEntityToModel(BuilderInfo info)
        {
            //从文件中读取模板
            Template template = velocity.GetTemplate("Template/IBatis/EntityToModel.vm");
            context.Put("list", info);

            //合并模板
            StringWriter writer = new StringWriter();
            template.Merge(context, writer);

            return writer.ToString();

        }

        public string BuilderModelToEntity(BuilderInfo info)
        {
            //从文件中读取模板
            Template template = velocity.GetTemplate("Template/IBatis/ModelToEntity.vm");
            context.Put("list", info);

            //合并模板
            StringWriter writer = new StringWriter();
            template.Merge(context, writer);

            return writer.ToString();

        }


	}
}
